from esphome.components.mipi import (
    MADCTL,
    MADCTL_ML,
    MADCTL_XFLIP,
    MODE_BGR,
    DriverChip,
)
from esphome.config_validation import UNDEFINED
from esphome.const import CONF_COLOR_ORDER, CONF_HEIGHT, CONF_MIRROR_X, CONF_MIRROR_Y

SDIR_CMD = 0xC7


class ST7701S(DriverChip):
    # The ST7701s does not use the standard MADCTL bits for x/y mirroring
    def add_madctl(self, sequence: list, config: dict):
        transform = self.get_transform(config)
        madctl = 0x00
        if config[CONF_COLOR_ORDER] == MODE_BGR:
            madctl |= 0x08
        if transform.get(CONF_MIRROR_Y):
            madctl |= MADCTL_ML
        sequence.append((MADCTL, madctl))
        sdir = 0
        if transform.get(CONF_MIRROR_X):
            sdir |= 0x04
            # XFLIP doesn't do anything in the ST7701S,
            # it's set in the madctl byte just so it can be reported at runtime by logconfig
            madctl |= MADCTL_XFLIP
        sequence.append((SDIR_CMD, sdir))
        return madctl

    @property
    def transforms(self) -> set[str]:
        """
        The ST7701 never supports axis swapping, and mirroring the y-axis only works for full height.
        """
        if self.get_default(CONF_HEIGHT) != 864:
            return {CONF_MIRROR_X}
        return {CONF_MIRROR_X, CONF_MIRROR_Y}


# fmt: off
st7701s = ST7701S(
    "ST7701S",
    width=480,
    height=864,
    swap_xy=UNDEFINED,
    hsync_front_porch=20,
    hsync_back_porch=10,
    hsync_pulse_width=10,
    vsync_front_porch=10,
    vsync_back_porch=10,
    vsync_pulse_width=10,
    pclk_frequency="16MHz",
    pclk_inverted=True,
    initsequence=(
        (0xFF, 0x77, 0x01, 0x00, 0x00, 0x10),  # Page 0
        (0xC0, 0x3B, 0x00), (0xC1, 0x0D, 0x02), (0xC2, 0x31, 0x05),
        (0xB0, 0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08, 0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18,),
        (0xB1, 0x00, 0x11, 0x19, 0x0E, 0x12, 0x07, 0x08, 0x08, 0x08, 0x22, 0x04, 0x11, 0x11, 0xA9, 0x32, 0x18,),
        (0xFF, 0x77, 0x01, 0x00, 0x00, 0x11),   # page 1
        (0xB0, 0x60), (0xB1, 0x32), (0xB2, 0x07), (0xB3, 0x80), (0xB5, 0x49), (0xB7, 0x85), (0xB8, 0x21), (0xC1, 0x78),
        (0xC2, 0x78), (0xE0, 0x00, 0x1B, 0x02),
        (0xE1, 0x08, 0xA0, 0x00, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x44, 0x44),
        (0xE2, 0x11, 0x11, 0x44, 0x44, 0xED, 0xA0, 0x00, 0x00, 0xEC, 0xA0, 0x00, 0x00),
        (0xE3, 0x00, 0x00, 0x11, 0x11),
        (0xE4, 0x44, 0x44),
        (0xE5, 0x0A, 0xE9, 0xD8, 0xA0, 0x0C, 0xEB, 0xD8, 0xA0, 0x0E, 0xED, 0xD8, 0xA0, 0x10, 0xEF, 0xD8, 0xA0,),
        (0xE6, 0x00, 0x00, 0x11, 0x11), (0xE7, 0x44, 0x44),
        (0xE8, 0x09, 0xE8, 0xD8, 0xA0, 0x0B, 0xEA, 0xD8, 0xA0, 0x0D, 0xEC, 0xD8, 0xA0, 0x0F, 0xEE, 0xD8, 0xA0,),
        (0xEB, 0x02, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40), (0xEC, 0x3C, 0x00),
        (0xED, 0xAB, 0x89, 0x76, 0x54, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x45, 0x67, 0x98, 0xBA,),
        (0xFF, 0x77, 0x01, 0x00, 0x00, 0x13),  # Page 3
        (0xE5, 0xE4),
        (0xFF, 0x77, 0x01, 0x00, 0x00, 0x10),  # Page 0
        (0xCD, 0x08),
    )
)

st7701s.extend(
    "MAKERFABS-4",
    width=480,
    height=480,
    color_order="RGB",
    invert_colors=True,
    pixel_mode="18bit",
    cs_pin=1,
    de_pin={
        "number": 45,
        "ignore_strapping_warning": True
    },
    hsync_pin=5,
    vsync_pin=4,
    pclk_pin=21,
    data_pins={
        "red": [39, 40, 41, 42, 2],
        "green": [0, 9, 14, 47, 48, 3],
        "blue": [6, 7, 15, 16, 8]
    }
)

st7701s.extend(
    "SEEED-INDICATOR-D1",
    width=480,
    height=480,
    mirror_x=True,
    mirror_y=True,
    invert_colors=True,
    pixel_mode="18bit",
    spi_mode="MODE3",
    data_rate="2MHz",
    hsync_front_porch=10,
    hsync_pulse_width=8,
    hsync_back_porch=50,
    vsync_front_porch=10,
    vsync_pulse_width=8,
    vsync_back_porch=20,
    cs_pin={"pca9554": None, "number": 4},
    de_pin=18,
    hsync_pin=16,
    vsync_pin=17,
    pclk_pin=21,
    pclk_inverted=False,
    data_pins={
        "red": [4, 3, 2, 1, 0],
        "green": [10, 9, 8, 7, 6, 5],
        "blue": [15, 14, 13, 12, 11]
    },
)

st7701s.extend(
    "UEDX48480021-MD80ET",
    width=480,
    height=480,
    pixel_mode="18bit",
    cs_pin=18,
    reset_pin=8,
    de_pin=17,
    vsync_pin={"number": 3, "ignore_strapping_warning": True},
    hsync_pin={"number": 46, "ignore_strapping_warning": True},
    pclk_pin=9,
    data_pins={
        "red": [40, 41, 42, 2, 1],
        "green": [21, 47, 48, 45, 38, 39],
        "blue": [10, 11, {"number": 12, "allow_other_uses": True}, {"number": 13, "allow_other_uses": True}, 14]
    },
    initsequence=(
        (0xFF, 0x77, 0x01, 0x00, 0x00, 0x13), (0xEF, 0x08), (0xFF, 0x77, 0x01, 0x00, 0x00, 0x10),
        (0xC0, 0x3B, 0x00), (0xC1, 0x0B, 0x02), (0xC2, 0x07, 0x02), (0xC7, 0x00), (0xCC, 0x10), (0xCD, 0x08),
        (0xB0, 0x00, 0x11, 0x16, 0x0E, 0x11, 0x06, 0x05, 0x09, 0x08, 0x21, 0x06, 0x13, 0x10, 0x29, 0x31, 0x18),
        (0xB1, 0x00, 0x11, 0x16, 0x0E, 0x11, 0x07, 0x05, 0x09, 0x09, 0x21, 0x05, 0x13, 0x11, 0x2A, 0x31, 0x18),
        (0xFF, 0x77, 0x01, 0x00, 0x00, 0x11),
        (0xB0, 0x6D), (0xB1, 0x37), (0xB2, 0x8B), (0xB3, 0x80), (0xB5, 0x43), (0xB7, 0x85),
        (0xB8, 0x20), (0xC0, 0x09), (0xC1, 0x78), (0xC2, 0x78), (0xD0, 0x88),
        (0xE0, 0x00, 0x00, 0x02),
        (0xE1, 0x03, 0xA0, 0x00, 0x00, 0x04, 0xA0, 0x00, 0x00, 0x00, 0x20, 0x20),
        (0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
        (0xE3, 0x00, 0x00, 0x11, 0x00),
        (0xE4, 0x22, 0x00),
        (0xE5, 0x05, 0xEC, 0xF6, 0xCA, 0x07, 0xEE, 0xF6, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
        (0xE6, 0x00, 0x00, 0x11, 0x00),
        (0xE7, 0x22, 0x00),
        (0xE8, 0x06, 0xED, 0xF6, 0xCA, 0x08, 0xEF, 0xF6, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
        (0xE9, 0x36, 0x00),
        (0xEB, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00),
        (0xED, 0xFF, 0xFF, 0xFF, 0xBA, 0x0A, 0xFF, 0x45, 0xFF, 0xFF, 0x54, 0xFF, 0xA0, 0xAB, 0xFF, 0xFF, 0xFF),
        (0xEF, 0x08, 0x08, 0x08, 0x45, 0x3F, 0x54),
        (0xFF, 0x77, 0x01, 0x00, 0x00, 0x13), (0xE8, 0x00, 0x0E), (0xFF, 0x77, 0x01, 0x00, 0x00, 0x00),
        (0x11, 0x00), (0xFF, 0x77, 0x01, 0x00, 0x00, 0x13), (0xE8, 0x00, 0x0C),
        (0xE8, 0x00, 0x00), (0xFF, 0x77, 0x01, 0x00, 0x00, 0x00)
    )
)

st7701s.extend(
    "ZX2D10GE01R-V4848",
    width=480,
    height=480,
    pixel_mode="18bit",
    cs_pin=21,
    de_pin=39,
    vsync_pin=48,
    hsync_pin=40,
    pclk_pin={"number": 45, "ignore_strapping_warning": True},
    pclk_frequency="15MHz",
    pclk_inverted=True,
    hsync_pulse_width=10,
    hsync_back_porch=10,
    hsync_front_porch=10,
    vsync_pulse_width=2,
    vsync_back_porch=12,
    vsync_front_porch=14,
    data_pins={
        "red": [10, 16, 9, 15, 46],
        "green": [8, 13, 18, 12, 11, 17],
        "blue": [{"number": 47, "allow_other_uses": True}, {"number": 41, "allow_other_uses": True}, 0, 42, 14]
    },
    initsequence=(
        (0xFF, 0x77, 0x01, 0x00, 0x00, 0x13), (0xEF, 0x08), (0xFF, 0x77, 0x01, 0x00, 0x00, 0x10), (0xC0, 0x3B, 0x00),
        (0xC1, 0x0B, 0x02), (0xC2, 0x07, 0x02), (0xCC, 0x10), (0xCD, 0x08),
        (0xB0, 0x00, 0x11, 0x16, 0x0e, 0x11, 0x06, 0x05, 0x09, 0x08, 0x21, 0x06, 0x13, 0x10, 0x29, 0x31, 0x18),
        (0xB1, 0x00, 0x11, 0x16, 0x0e, 0x11, 0x07, 0x05, 0x09, 0x09, 0x21, 0x05, 0x13, 0x11, 0x2a, 0x31, 0x18),
        (0xFF, 0x77, 0x01, 0x00, 0x00, 0x11), (0xB0, 0x6d), (0xB1, 0x37), (0xB2, 0x81), (0xB3, 0x80), (0xB5, 0x43),
        (0xB7, 0x85), (0xB8, 0x20), (0xC1, 0x78), (0xC2, 0x78), (0xD0, 0x88), (0xE0, 0x00, 0x00, 0x02),
        (0xE1, 0x03, 0xA0, 0x00, 0x00, 0x04, 0xA0, 0x00, 0x00, 0x00, 0x20, 0x20),
        (0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
        (0xE3, 0x00, 0x00, 0x11, 0x00), (0xE4, 0x22, 0x00),
        (0xE5, 0x05, 0xEC, 0xA0, 0xA0, 0x07, 0xEE, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
        (0xE6, 0x00, 0x00, 0x11, 0x00), (0xE7, 0x22, 0x00),
        (0xE8, 0x06, 0xED, 0xA0, 0xA0, 0x08, 0xEF, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
        (0xEB, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00),
        (0xED, 0xFF, 0xFF, 0xFF, 0xBA, 0x0A, 0xBF, 0x45, 0xFF, 0xFF, 0x54, 0xFB, 0xA0, 0xAB, 0xFF, 0xFF, 0xFF),
        (0xEF, 0x10, 0x0D, 0x04, 0x08, 0x3F, 0x1F),
        (0xFF, 0x77, 0x01, 0x00, 0x00, 0x13), (0xEF, 0x08), (0xFF, 0x77, 0x01, 0x00, 0x00, 0x00)
    )
)
